package com.slipper.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Base64;
import java.util.Date;

public class DesEncryptor {
    private static final Logger logger = LoggerFactory.getLogger(DesEncryptor.class);

    public static final int INT_PRIM_NUMBER = 95;
    public static final int INT_RETURN_LOOP = 94;
    private static final String MY_FLAG_PREFIX = "trade";
    private static final String MY_FLAG_SUFFIX = "flag";

    /**
     * 解密方法 strCode 需解密的字符串 解密后的字符串 1.0
     */
    private static String decode(String strCode) {
        String strOriginal;
        int intRnd;
        String strRnd;
        int intStrLen;
        String strDecodeMe = "";

        if (strCode.isEmpty()) {
            return strDecodeMe;
        }
        intStrLen = strCode.length() - 1;

        strRnd = strCode.substring(intStrLen / 2, intStrLen / 2 + 1);
        intRnd = strRnd.hashCode() - startChar();
        strCode = strCode.substring(0, intStrLen / 2) + strCode.substring(intStrLen / 2 + 1, intStrLen + 1);
        strOriginal = new DesEncryptor().loopCode(strCode, INT_RETURN_LOOP - intRnd);
        strDecodeMe = strOriginal;
        return strDecodeMe;
    }

    /**
     * 加密方法.随机取得加密的循环次数，使得每次加密所得的秘文会有所不同 strOriginal 需加密的字符串 加密后的字符串 1.0
     */
    private static String encode(String strOriginal) {
        String strCode;
        int intRnd;
        char rnd;
        int intStrLen;
        String strCodeMe = "";
        if (strOriginal.isEmpty()) {
            return strCodeMe;
        }
        // 2 到 93 之间的随即数，即同一原文可能获得93种不同的秘文
        intRnd = (int) (Math.random() * (INT_RETURN_LOOP - 2) + 2);
        strCode = new DesEncryptor().loopCode(strOriginal, intRnd);
        // 对随机数作偏移加密
        rnd = (char) (intRnd + startChar());
        intStrLen = strCode.length();
        strCodeMe = strCode.substring(0, intStrLen / 2) + rnd + strCode.substring(intStrLen / 2, intStrLen);
        if (strCodeMe.contains("??")) {
            return encode(strOriginal);
        } else {
            return strCodeMe;
        }
    }

    // 基础的凯撒算法,并对于每一位增加了偏移
    private String kaiserCode(String strOriginal) {
        StringBuilder strCode = new StringBuilder();
        for (int i = 0; i < strOriginal.length(); i++) {
            int intChar = strOriginal.substring(i, i + 1).hashCode();
            int intTmp = intChar - startChar();
            intTmp = (intTmp * INT_PRIM_NUMBER + i + 1) % this.maxChar() + startChar();
            strCode.append((char) (intTmp));
        }
        return strCode.toString();
    }

    // 循环调用凯撒算法一定次数后，可以取得原文
    private String loopCode(String strOriginal, int intLoopCount) {
        String strCode = strOriginal;
        for (int i = 0; i < intLoopCount; i++) {
            strCode = this.kaiserCode(strCode);
        }
        return strCode;
    }

    /**
     * 加密
     */
    public static String encrypt(String pw) {
        if (pw == null || pw.isEmpty()) {
            return pw;
        }

        return new String(Base64.getEncoder().encode((MY_FLAG_PREFIX + pw + MY_FLAG_SUFFIX).getBytes()));
    }

    /**
     * 解密
     */
    public static String decrypt(String pw) {
        if (pw == null || pw.isEmpty()) {
            return pw;
        }

        try {
            String pw1 = encode(pw);
            String pw2 = decode(pw1);
            byte[] bt = Base64.getDecoder().decode(pw2);
            pw2 = new String(bt);
            pw2 = pw2.substring(MY_FLAG_PREFIX.length());
            pw2 = pw2.substring(0, pw2.length() - MY_FLAG_SUFFIX.length());
            return pw2;
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    private int maxChar() {
        String str1 = "~";
        String str2 = "!";
        return str1.hashCode() - str2.hashCode() + 1;
    }

    private static int startChar() {
        String str1 = "!";
        return str1.hashCode();
    }

    public static void main(String[] args) throws Exception {
        // String url = "http://localhost:6004/admin";
        String url = "http://192.168.0.103/admin";
        String id = "07ebd9c3d68a441a86c7a1f3b18515a3";
        String password = "e10adc3949ba59abbe56e057f20f883e";
        System.out.println(url + "/?_Login_Code_="
                + encrypt(id + "@" + password + "@" + DateUtil.formatTime(new Date())));
    }
}
